package com.xz.stu.server.service.impl;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONNull;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.stu.server.entity.Department;
import com.xz.stu.server.entity.StuClass;
import com.xz.stu.server.entity.Teacher;
import com.xz.stu.server.entity.Teacher;
import com.xz.stu.server.mapper.TeacherMapper;
import com.xz.stu.server.service.DepartmentService;
import com.xz.stu.server.service.TeacherService;
import com.xz.stu.server.vo.teacher.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

/**
 * @author 熊磊
 * @description 针对表【school_teacher】的数据库操作Service实现
 * @createDate 2025-03-01 15:18:51
 */
@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher>
        implements TeacherService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Resource
    private DepartmentService  departmentService;
    @Resource
    private AdminUserService    adminUserService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private RoleMapper roleMapper;

    @Override
    public Long createTeacher(TeacherCreateReqVO createReqVO) {
        Teacher teacher = BeanUtils.toBean(createReqVO, Teacher.class);
        //判断工号是否已存在
        if (this.getOne(new LambdaQueryWrapper<Teacher>().eq(Teacher::getTeacherId, createReqVO.getTeacherId())) != null) {
            throw new ServiceException(new ErrorCode(100000000,"工号已存在"));
        }
        //判断院系是否存在
        if (departmentService.getById(createReqVO.getDeptId()) == null) {
            throw new ServiceException(new ErrorCode(100000000,"院系不存在"));
        }
        AdminUserDO adminUserDO = new AdminUserDO();
        adminUserDO.setUsername(teacher.getTeacherId());
        adminUserDO.setPassword(passwordEncoder.encode("123456"));
        adminUserDO.setNickname(teacher.getName());
        adminUserDO.setMobile(teacher.getPhone());
        adminUserService.save(adminUserDO);
        teacher.setUserId(adminUserDO.getId());
        //添加角色信息
        RoleDO roleDO = roleMapper.selectOne(RoleDO::getName, "学生");
        UserRoleDO userRoleDO = new UserRoleDO();
        userRoleDO.setUserId(adminUserDO.getId());
        userRoleDO.setRoleId(roleDO.getId());
        userRoleMapper.insert(userRoleDO);
        this.save(teacher);
        return teacher.getId();
    }

    @Override
    public void updateTeacher(TeacherUpdateReqVO updateReqVO) {
        Teacher teacher = BeanUtils.toBean(updateReqVO, Teacher.class);
        //判断工号是否已存在
        if (this.getOne(new LambdaQueryWrapper<Teacher>().eq(Teacher::getTeacherId, updateReqVO.getTeacherId())) != null) {
            throw new ServiceException(new ErrorCode(100000000,"工号已存在"));
        }
        //判断院系是否存在
        if (departmentService.getById(updateReqVO.getDeptId()) == null) {
            throw new ServiceException(new ErrorCode(100000000,"院系不存在"));
        }
        this.updateById(teacher);
    }

    @Override
    @Transactional
    public void deleteTeacher(List<Long> id) {
        List<Long> userIds = this.listByIds(id).stream().map(Teacher::getUserId).collect(Collectors.toList());
        userRoleMapper.delete(new LambdaQueryWrapper<UserRoleDO>().in(UserRoleDO::getUserId, userIds));
        adminUserService.removeByIds(userIds);
        this.removeByIds(id);
    }

    @Override
    public TeacherRespVO getTeacher(Long id) {
        Teacher teacher = this.getById(id);
        TeacherRespVO teacherRespVO = BeanUtils.toBean(teacher, TeacherRespVO.class);
        return teacherRespVO;
    }

    @Override
    public List<TeacherRespVO> getTeacherList(TeacherListReqVO listReqVO) {
        List<Teacher> list = this.list();
        return BeanUtils.toBean(list, TeacherRespVO.class);
    }

    @Override
    public PageResult<TeacherRespVO> getTeacherListPage(TeacherListPageReqVO listReqVO) {
        Map<Long, String> deptmap = departmentService.list().stream().collect(Collectors.toMap(Department::getId, Department::getDeptName));
        LambdaQueryWrapper<Teacher> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 这里根据具体的 TeacherListPageReqVO 中的属性进行条件筛选，假设 Teacher 实体中有相应的属性
        // 以下仅为示例，需要根据实际情况修改
        lambdaQueryWrapper.eq(Objects.nonNull(listReqVO.getTeacherId()), Teacher::getTeacherId, listReqVO.getTeacherId())
                .eq(Objects.nonNull(listReqVO.getGender()), Teacher::getGender, listReqVO.getGender())
                .eq(Objects.nonNull(listReqVO.getDeptId()), Teacher::getDeptId, listReqVO.getDeptId())
                .like(Objects.nonNull(listReqVO.getTitle()), Teacher::getTitle, listReqVO.getTitle())
                .like(Objects.nonNull(listReqVO.getName()), Teacher::getName, listReqVO.getName());
        Page<Teacher> page = this.page(new Page<>(listReqVO.getPageNo(), listReqVO.getPageSize()), lambdaQueryWrapper);
        if (page != null) {
            List<TeacherRespVO> teacherRespVOList = BeanUtils.toBean(page.getRecords(), TeacherRespVO.class);
            teacherRespVOList.forEach(teacherRespVO -> {
                teacherRespVO.setDeptName(deptmap.get(teacherRespVO.getDeptId()));
            });
            return new PageResult<>(teacherRespVOList, page.getTotal());
        }
        return null;
    }

    @Override
    @Transactional
    public CommonResult<Map<String, String>> importTeachers(List<TeacherTemplateVO> teachers) {
        HashMap<String, String> map = new HashMap<>();
        if (teachers == null || teachers.isEmpty()) {
            map.put("code", "301");
            map.put("msg", "文件为空，请选择有效的 Excel 文件。");
            return success(map);
        }
        List<Department> departmentList = departmentService.list();

        List<TeacherTemplateAbnormalVO> list = new ArrayList<>();
        this.extracted(teachers, departmentList, list);
        if (!list.isEmpty()){
            Long id = Objects.requireNonNull(SecurityFrameworkUtils.getLoginUser()).getId();
            //构架key
            String key = "teacher:import:abnormal:" + id;
            //将异常存入redis
            redisTemplate.opsForValue().set(key, JsonUtils.toJsonPrettyString(list), 1, TimeUnit.MINUTES);
            map.put("code", "101");
            map.put("msg", "导入失败，为您下载错误信息。");
            return success(map);
        }
        Map<String, Long> longMap = departmentList.stream().collect(Collectors.toMap(Department::getDeptName, Department::getId));
        List<Teacher> teacherList = teachers.stream().map(teacher -> {
            Teacher stu = BeanUtils.toBean(teacher, Teacher.class);
            stu.setGender(teacher.getGenderC().equals("男") ? 0 : 1);
            AdminUserDO adminUserDO = new AdminUserDO();
            adminUserDO.setUsername(teacher.getTeacherId());
            adminUserDO.setPassword(passwordEncoder.encode("123456"));
            adminUserDO.setNickname(teacher.getName());
            adminUserDO.setMobile(teacher.getPhone());
            adminUserService.save(adminUserDO);
            stu.setUserId(adminUserDO.getId());
            stu.setDeptId(longMap.get(teacher.getDeptName()));
            //添加角色信息
            RoleDO roleDO = roleMapper.selectOne(RoleDO::getName, "教师");
            UserRoleDO userRoleDO = new UserRoleDO();
            userRoleDO.setUserId(adminUserDO.getId());
            userRoleDO.setRoleId(roleDO.getId());
            userRoleMapper.insert(userRoleDO);
            return stu;
        }).collect(Collectors.toList());
        this.saveBatch(teacherList);
        map.put("code", "200");
        map.put("msg","导入成功，共导入 " + teachers.size() + " 条教师信息。");
        return success(map);
    }

    private void extracted(List<TeacherTemplateVO> teachers, List<Department> departmentList, List<TeacherTemplateAbnormalVO> list) {
        List<String> teacherIds = this.list().stream().map(Teacher::getTeacherId).collect(Collectors.toList());

        List<String> deptList = departmentList.stream().map(Department::getDeptName).collect(Collectors.toList());
        for (TeacherTemplateVO teacher : teachers) {
            //判断学号是否重复
            if (teacherIds.contains(teacher.getTeacherId())){
                TeacherTemplateAbnormalVO teacherTemplateAbnormalVO = BeanUtils.toBean(teacher, TeacherTemplateAbnormalVO.class);
                teacherTemplateAbnormalVO.setErrorMsg("学号重复");
                list.add(teacherTemplateAbnormalVO);
            }
            //判断院系是否存在
            if (!deptList.contains(teacher.getDeptName())){
                TeacherTemplateAbnormalVO teacherTemplateAbnormalVO = BeanUtils.toBean(teacher, TeacherTemplateAbnormalVO.class);
                teacherTemplateAbnormalVO.setErrorMsg("院系不存在");
                list.add(teacherTemplateAbnormalVO);
            }
        }
    }
}
